package cn.zn.modules.budget.cur.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.zn.framework.common.exception.RRException;
import cn.zn.modules.budget.cur.dao.TBudgetInfoDetailFreezsMapper;
import cn.zn.modules.budget.cur.entity.TBudgetInfoDetailFreezs;
import cn.zn.modules.budget.cur.service.TBudgetInfoDetailFreezsService;
import cn.zn.modules.budget.cur.service.TBudgetInfoService;
import cn.zn.modules.budget.inter.BudgetFreezsInter;
import cn.zn.modules.budget.inter.vo.BudgetFreezsSaveRspVO;
import cn.zn.modules.budget.inter.vo.BudgetFreezsVO;
import cn.zn.modules.budget.inter.vo.BudgetSGForFreezsVO;
import cn.zn.modules.budget.vo.BudgetMoneyVO;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Service
public class TBudgetInfoDetailFreezsServiceImpl extends ServiceImpl<TBudgetInfoDetailFreezsMapper, TBudgetInfoDetailFreezs> implements TBudgetInfoDetailFreezsService, BudgetFreezsInter {

    @Autowired
    TBudgetInfoService tBudgetInfoService;

    @Override
    public BudgetFreezsSaveRspVO saveBudgetFreezs(BudgetFreezsVO budgetFreezsVO) {
        BudgetMoneyVO budgetMoneyVO = tBudgetInfoService.findAvailableBudget(budgetFreezsVO.getDeptCode(),
                budgetFreezsVO.getProjectCode(),
                budgetFreezsVO.getCateCode());
        if (budgetMoneyVO == null) {
            throw new RRException("未查询到需要的预算信息");
        }
        // 是否超预算
        Double money = budgetFreezsVO.getMoney();
        if (StrUtil.isNotBlank(budgetFreezsVO.getId())) {
            // 已存在的冻结
            TBudgetInfoDetailFreezs detailFreezs = this.getById(budgetFreezsVO.getId());
            // 待保存冻结的预算与老的相同，验证多出部分
            if (StrUtil.equals(detailFreezs.getTBudgetInfoId(), budgetMoneyVO.getId())) {
                money = BigDecimal.valueOf(money - detailFreezs.getMoney()).setScale(2, BigDecimal.ROUND_HALF_UP)
                        .doubleValue();
            }
        }
        BigDecimal availableBD = new BigDecimal(budgetMoneyVO.availableMoney());
        BigDecimal moneyBD = new BigDecimal(money != null ? money : 0);
        if (availableBD.compareTo(moneyBD) < 0) {
            throw new RRException("预算不足");
        }
        TBudgetInfoDetailFreezs detailFreezs = TBudgetInfoDetailFreezs.builder()
                .tBudgetInfoId(budgetMoneyVO.getId())
                .state(1)
                .money(budgetFreezsVO.getMoney())
                .processCode(budgetFreezsVO.getType())
                .build();
        if (StrUtil.isNotBlank(budgetFreezsVO.getId())) {
            // 更新冻结
            detailFreezs.setId(budgetFreezsVO.getId());
            this.updateById(detailFreezs);
        } else {
            // 新增冻结
            this.save(detailFreezs);
        }
        return BudgetFreezsSaveRspVO.builder()
                .infoId(budgetMoneyVO.getId())
                .freezsId(detailFreezs.getId())
                .build();
    }

    @Override
    public void deleteBudgetFreezs(List<String> freezsIds) {
        this.removeByIds(freezsIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String converBudgetFreezs(String freezsId, String processCode, String remark) {
        TBudgetInfoDetailFreezs freezsNew = new TBudgetInfoDetailFreezs();
        TBudgetInfoDetailFreezs freezsOld = super.getById(freezsId);
        BeanUtils.copyProperties(freezsOld, freezsNew);
        freezsNew.setId(null);
        freezsNew.setProcessCode(processCode);
        super.save(freezsNew);
        // 作废原冻结
        super.update(new UpdateWrapper<TBudgetInfoDetailFreezs>().eq("ID_", freezsId)
                .set("STATE_", 3)
                .set("REMARK_", remark)
        );
        return freezsNew.getId();
    }

    @Override
    public List<BudgetSGForFreezsVO> findSGByFreeze(List<String> freezsIds) {
        if (freezsIds == null || freezsIds.size() == 0) {
            return CollUtil.newArrayList();
        }
        List<BudgetSGForFreezsVO> sgForFreezs = this.baseMapper.findSGForFreezs(freezsIds);
        // key=budgetId
        Map<String, List<BudgetSGForFreezsVO>> freezsSGMap = CollUtil.newHashMap();
        sgForFreezs.forEach(o -> {
            if (!freezsSGMap.containsKey(o.getBudgetInfoId())) {
                freezsSGMap.put(o.getBudgetInfoId(), CollUtil.newArrayList());
            }
            freezsSGMap.get(o.getBudgetInfoId()).add(o);
        });
        List<Map<String, String>> sgByInfos = tBudgetInfoService.findSGByInfo(CollUtil.newArrayList(freezsSGMap.keySet()));
        sgByInfos.forEach(o -> {
            freezsSGMap.get(o.get("budgetInfoId").toLowerCase()).forEach(o1 -> {
                o1.getCanChooses().add(o);
            });
        });
        return sgForFreezs;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSGBatch(List<BudgetSGForFreezsVO> budgetSGForFreezsVOS) {
        budgetSGForFreezsVOS.forEach(o -> {
            UpdateWrapper<TBudgetInfoDetailFreezs> updateWrapper = Wrappers.update();
            updateWrapper.eq("ID_", o.getFreezsId());
            updateWrapper.set("TYPE_CODE_", "001");
            updateWrapper.set("TYPE_ATTR_", o.getCanChooses().get(0).get("sgProjectCode"));
            this.update(updateWrapper);
        });
    }

    @Override
    public List<TBudgetInfoDetailFreezs> queryFreezsApply(String budgetInfoId, Map<String, Object> params) {
        TBudgetInfoDetailFreezs tBudgetInfoDetailFreezs = BeanUtil.mapToBean(params, TBudgetInfoDetailFreezs.class, true);
        return baseMapper.queryFreezsApply(budgetInfoId, tBudgetInfoDetailFreezs);
    }
}
